#include<bits/stdc++.h>
using namespace std;
int T;
int n,m,L,V,ans,ans2;
int d,v,a,st[100005],ed[100005],pot[100005];
int num[100005];
int vis[1000005];
struct segmenttree{
    int l,r;
    bool flag;
}tree[4*1000005];
struct node{
    vector<int> vec;
}aa[100005];
bool cmp(node x,node y){
    return x.vec.size()<y.vec.size();
}
int mm[1000005];
int lc(int p){
    return p*2;
}
int rc(int p){
    return p*2+1;
}
void push_up(int p){
    if(tree[lc(p)].flag==1||tree[rc(p)].flag==1)tree[p].flag=1;
    else tree[p].flag=0;
}
void build(int p,int pl,int pr){
    tree[p].l=pl;
    tree[p].r=pr;
    if(pl==pr){
        tree[p].flag=vis[pl];
        return;
    }
    int mid=(pl+pr)/2;
    build(lc(p),pl,mid);
    build(rc(p),mid+1,pr);
    push_up(p);
}
void update(int p,int l,int r,int inx){
    if(tree[p].l==tree[p].r){
        if(vis[tree[p].l]>=1){
            aa[mm[tree[p].l]].vec.push_back(tree[p].l);
            vis[tree[p].l]++;
        }
        return;
    }
    int mid=(tree[p].l+tree[p].r)/2;
    if(l<=mid)update(lc(p),l,r,inx);
    if(r>mid)update(rc(p),l,r,inx);
}
bool query(int p,int l,int r){
    if(l<=tree[p].l&&tree[p].r<=r){
        return tree[p].flag;
    }
    bool f=0;
    int mid=(tree[p].l+tree[p].r)/2;
    if(l<=mid)f=f||query(lc(p),l,r);
    if(r>mid)f=f||query(rc(p),l,r);
    return f;
}
int main(){
    //CCF give me 20 points,I'm your son
    freopen("detect.in","r",stdin);
    freopen("detect.out","w",stdout);
    scanf("%d",&T);
    while(T--){
        memset(vis,0,sizeof(vis));
        memset(tree,0,sizeof(tree));
        ans=0;
        ans2=0;
        scanf("%d",&n);
        scanf("%d",&m);
        scanf("%d",&L);
        scanf("%d",&V);
        for(int i=1;i<=n;i++){
            scanf("%d",&d);
            scanf("%d",&v);
            scanf("%d",&a);
            if(a!=0){
                int x=V*V-v*v;
                int y=2*a;
                if(a<0&&v<=V)st[i]=-1,ed[i]=-1;
                else if(a>0&&v>V)st[i]=d,ed[i]=L;
                else if(a>0&&v==V)st[i]=d+1,ed[i]=L;
                else{
                    if(a>0)st[i]=min(L+1,d+x/y),ed[i]=L;
                    else if(a<0&&x%y==0)st[i]=d,ed[i]=min(L,d-1+x/y);
                    else if(a<0&&x%y!=0)st[i]=d,ed[i]=min(L,d+x/y);
                }
            }
            else{
                if(v>V)st[i]=d,ed[i]=L;
                else st[i]=-1,ed[i]=-1;
            }
        }
        for(int i=1;i<=m;i++){
            scanf("%d",&pot[i]);
            mm[pot[i]]=i;
            vis[pot[i]]=1;
        }
        build(1,1,L);
        for(int i=1;i<=n;i++){
            if(st[i]!=-1&&ed[i]!=-1&&st[i]<=ed[i]){
                if(query(1,st[i],ed[i])==1)ans++;
                update(1,st[i],ed[i],i);
            }
        }
        for(int i=1;i<=m;i++){
            vis[pot[i]]--;
        }
        sort(aa+1,aa+m+1,cmp);
        bool ff;
        for(int i=1;i<=m;i++){
            if(aa[i].vec.empty())ans2++;
            ff=1;
            for(auto it=aa[i].vec.begin();it!=aa[i].vec.end();it++){
                if(vis[*it]==1){
                    ff=false;
                    break;
                }
            }
            if(ff){
                ans2++;
                for(auto it=aa[i].vec.begin();it!=aa[i].vec.end();it++){
                    vis[*it]--;
                }
            }
        }
        printf("%d %d\n",ans,ans2);
    }
    return 0;
}
